home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / C / Frameworks / Extension Shell 1.4 / Extension Shell 1.4 (Source) / InstallCode.c < prev    next >
Text File  |  1995-11-03  |  13KB  |  545 lines

  1. /*    NAME:
  2.         InstallCode.c
  3.  
  4.     WRITTEN BY:
  5.         Dair Grant
  6.                 
  7.     DESCRIPTION:
  8.         Routines for installing various code resources.
  9.         
  10.     ___________________________________________________________________________
  11. */
  12. //=============================================================================
  13. //        Include files                                                                     
  14. //-----------------------------------------------------------------------------
  15. #include <Memory.h>
  16. #include <Gestalt.h>
  17. #include <Shutdown.h>
  18. #include <Timer.h>
  19. #include "ES.h"
  20. #include "ES Address Table.h"
  21. #include "InstallCode.h"
  22.  
  23.  
  24.  
  25.  
  26.  
  27.  
  28.  
  29.  
  30.  
  31.  
  32.  
  33.  
  34.  
  35.  
  36.  
  37. //=============================================================================
  38. //        Private function prototypes                                                                     
  39. //-----------------------------------------------------------------------------
  40. OSErr    InstallTrapPatch(short i, Ptr theCode);
  41. OSErr    InstallGestaltSelector(short i, Ptr theCode);
  42. OSErr    InstallShutdownTask(short i, Ptr theCode);
  43. OSErr    InstallVBLTask(short i, Ptr theCode);
  44. OSErr    InstallLowMemFilter(short i, Ptr theCode);
  45. OSErr    InstallCodeBlock(short i, Ptr theCode);
  46. OSErr    InstallTimeManagerTask(short i, Ptr theCode);
  47.  
  48.  
  49.  
  50.  
  51.  
  52.  
  53.  
  54.  
  55.  
  56.  
  57.  
  58.  
  59.  
  60.  
  61.  
  62. //=============================================================================
  63. //        Global variables                                                                 
  64. //-----------------------------------------------------------------------------
  65. extern ESParamBlock            gTheParamBlock;
  66. extern ESAddressTable        *gTheESAddressTable;
  67.  
  68.  
  69.  
  70.  
  71.  
  72.  
  73.  
  74.  
  75.  
  76.  
  77.  
  78.  
  79.  
  80.  
  81.  
  82. //=============================================================================
  83. //        InstallCode : Install a code resource depending on its type.                                                                 
  84. //-----------------------------------------------------------------------------
  85. //        Note :    We get the index of something in gTheParamBlock.theCodeResources
  86. //                and case out on its type to do the installation. If any error
  87. //                occurs, we return the error code - our caller fills in the
  88. //                details in gTheParamBlock.
  89. //-----------------------------------------------------------------------------
  90. OSErr InstallCode(short i)
  91. {    Handle        theHnd;
  92.     OSErr        theErr;
  93.     Ptr            theCode;
  94.     
  95.     
  96.  
  97.  
  98.     // Get the code resource we're after, and return if it wasn't there.
  99.     theHnd = GetResource(gTheParamBlock.theCodeResources[i].resType,
  100.                          gTheParamBlock.theCodeResources[i].resID);
  101.     if (theHnd == nil)
  102.         return(resNotFound);
  103.  
  104.  
  105.     
  106.     // Unlock the resource, compact the heap, then lock it down. We then
  107.     // detach it so it stays around after Extension Shell is gone.
  108.     HUnlock(theHnd);
  109.     ResrvMem(GetHandleSize(theHnd));
  110.     HLock(theHnd);
  111.     DetachResource(theHnd);
  112.  
  113.  
  114.  
  115.     // Get a clean address from the handle
  116.     theCode = (Ptr) StripAddress(*theHnd);
  117.  
  118.  
  119.  
  120.     // Now case out on the type of the code, and call the install routine
  121.     switch(gTheParamBlock.theCodeResources[i].codeType) {
  122.         case kTrapPatchType:
  123.              theErr = InstallTrapPatch(i, theCode);
  124.              break;
  125.              
  126.         case kGestaltSelectorType:
  127.              theErr = InstallGestaltSelector(i, theCode);
  128.              break;
  129.              
  130.         case kShutdownTaskType:
  131.              theErr = InstallShutdownTask(i, theCode);
  132.              break;
  133.              
  134.         case kVBLTaskType:
  135.              theErr = InstallVBLTask(i, theCode);
  136.              break;
  137.         
  138.         case kLowMemFilterType:
  139.              theErr = InstallLowMemFilter(i, theCode);
  140.              break;
  141.         
  142.         case kCodeBlockType:
  143.              theErr = InstallCodeBlock(i, theCode);
  144.              break;
  145.         
  146.         case kTimeManagerTaskType:
  147.              theErr = InstallTimeManagerTask(i, theCode);
  148.              break;
  149.         
  150.         default:
  151.              theErr = noErr;
  152.     }
  153.  
  154.     
  155.     // Return any errors that occurred    
  156.     return(theErr);
  157.  
  158.  
  159.  
  160.  
  161.  
  162.  
  163.  
  164.  
  165.  
  166.  
  167.  
  168.  
  169.  
  170.  
  171.  
  172. //=============================================================================
  173. //        InstallESAddressTable : Install an address table.
  174. //-----------------------------------------------------------------------------
  175. //        Note :    We install the Gestalt selector, call Gestalt to obtain the
  176. //                address of the address table, and leave the result in
  177. //                gTheESAddressTable.
  178. //
  179. //                Because the address table is so fundamental, any failure
  180. //                to load, install, or call it drops us into MacsBug.
  181. //-----------------------------------------------------------------------------
  182. void InstallESAddressTable(void)
  183. {    Handle            theHnd;
  184.     OSErr            theErr;
  185.     ProcPtr            theCode;    
  186.  
  187.  
  188.  
  189.     // Load the AddressTable Gestalt selector, and install it with NewGestalt.
  190.     theHnd = GetResource(kAddrsTableCodeType, kAddrsTableCodeID);
  191.     if (theHnd == nil)
  192.         DebugStr("\pExtension Shell - couldn't find Address Table resource");
  193.     
  194.     
  195.     // We have it, so lock it in place
  196.     HUnlock(theHnd);
  197.     ResrvMem(GetHandleSize(theHnd));
  198.     HLock(theHnd);
  199.     DetachResource(theHnd);
  200.     
  201.     
  202.     // Get a clean address from the handle
  203.     theCode = (ProcPtr) StripAddress(*theHnd);
  204.     
  205.     
  206.     // Install the address table as a Gestalt selector
  207.     theErr = NewGestalt(gTheParamBlock.addressTableSelector,
  208.                                 NewSelectorFunctionProc(theCode));
  209.     if (theErr != noErr)
  210.         DebugStr("\pExtension Shell - couldn't install AddressTable");
  211.         
  212.  
  213.     // Call Gestalt to get the address of the address table
  214.     theErr = Gestalt(gTheParamBlock.addressTableSelector, (long *) &gTheESAddressTable);
  215.     if (theErr != noErr)
  216.         DebugStr("\pExtension Shell - couldn't call AddressTable");
  217. }
  218.  
  219.  
  220.  
  221.  
  222.  
  223.  
  224.  
  225.  
  226.  
  227.  
  228.  
  229.  
  230.  
  231.  
  232.  
  233. //=============================================================================
  234. //        InstallTrapPatch : Install a trap patch.                                                         
  235. //-----------------------------------------------------------------------------
  236. //        Note :    Given a trap word and a pointer to the new routine, we save
  237. //                the original entry in the dispatch table and insert the new
  238. //                one.
  239. //
  240. //                We assume that the trap *is* implemented. If globalPatch is
  241. //                true, the patch is applied to all applications (this is the
  242. //                default behaviour). If globalPatch is false, the patch only
  243. //                takes affect in the application appName. (THIS FEATURE IS
  244. //                NOT IMPLEMENTED YET)
  245. //-----------------------------------------------------------------------------
  246. OSErr InstallTrapPatch(short i, Ptr theCode)
  247. {    short        trapWord;
  248.     TrapType    trapType;
  249.     ProcPtr        oldCodeAddress;
  250.     
  251.     
  252.     
  253.     // Find out what we need to know
  254.      trapWord = gTheParamBlock.theCodeResources[i].theCodeThing.theTrapPatch.trapWord;
  255.     trapType = (trapWord & 0x0800) ? ToolTrap : OSTrap;
  256.  
  257.  
  258.     // Replace the old value in the dispatch table with the new value.
  259.     oldCodeAddress = (ProcPtr) StripAddress((Ptr) NGetTrapAddress(trapWord, trapType));
  260.     NSetTrapAddress((UniversalProcPtr) theCode, trapWord, trapType);
  261.     
  262.     
  263.     
  264.     // Handle globalPatch and appName
  265.     //
  266.     // THIS FEATURE IS NOT IMPLEMENTED YET - IT WOULD NEED SOME KIND OF
  267.     // GENERIC EXTENSION SHELL PATCH TO SOMETHING LIKE _INITALLPACKS OR
  268.     // _INITGRAF, AND THEN THE APPLICATION OF PATCHES DEPENDING ON
  269.     // THE APPLICATION BEING EXECUTED.
  270.     //
  271.     //
  272.     
  273.     
  274.     
  275.     // Fill in the entry in the address table and save the address of the new code.
  276.     gTheESAddressTable->theTable[i]                    = oldCodeAddress;
  277.     gTheParamBlock.theCodeResources[i].theAddress    = theCode;
  278.  
  279.  
  280.     // Return any errors
  281.     return(noErr);
  282. }
  283.  
  284.  
  285.  
  286.  
  287.  
  288.  
  289.  
  290.  
  291.  
  292.  
  293.  
  294.  
  295.  
  296.  
  297.  
  298. //=============================================================================
  299. //        InstallGestaltSelector : Install a Gestalt Selector.                                                         
  300. //-----------------------------------------------------------------------------
  301. OSErr InstallGestaltSelector(short i, Ptr theCode)
  302. {    OSErr                    theErr;
  303.     SelectorFunctionUPP        theUPP;
  304.     AGestaltSelector        *theGestaltInfo;
  305.  
  306.  
  307.  
  308.  
  309.     // Find out what we need to know
  310.     theGestaltInfo = &gTheParamBlock.theCodeResources[i].theCodeThing.theGestaltSelector;
  311.     theUPP = NewSelectorFunctionProc(theCode);
  312.     
  313.  
  314.     
  315.     // Try and install the routine
  316.     theErr = NewGestalt(theGestaltInfo->theSelector, theUPP);
  317.  
  318.     
  319.     
  320.     // If the selector exists, replace it if we're allowed to, and save
  321.     // the address of the old routine in the address table
  322.     if (theErr == gestaltDupSelectorErr && theGestaltInfo->overwriteExistingSelector)
  323.         theErr = ReplaceGestalt(theGestaltInfo->theSelector, theUPP,
  324.                                 (SelectorFunctionUPP *) &gTheESAddressTable->theTable[i]);
  325.     
  326.     
  327.     
  328.     // If there wasn't a problem, save the address of the new code. The address
  329.     // table is only used if we need to get access to the old Gestalt routine.
  330.     if (theErr == noErr)
  331.         gTheParamBlock.theCodeResources[i].theAddress = theCode;
  332.         
  333.         
  334.     
  335.     // Return any errors
  336.     return(theErr);
  337. }
  338.  
  339.  
  340.  
  341.  
  342.  
  343.  
  344.  
  345.  
  346.  
  347.  
  348.  
  349.  
  350.  
  351.  
  352.  
  353. //=============================================================================
  354. //        InstallShutdownTask : Install a Shutdown Task.                                                         
  355. //-----------------------------------------------------------------------------
  356. OSErr InstallShutdownTask(short i, Ptr theCode)
  357. {
  358.  
  359.  
  360.     // Install the task with its flags and save the address in gTheParamBlock.
  361.     // We don't use the address table at all.
  362.     ShutDwnInstall(NewShutDwnProc(theCode),
  363.                    gTheParamBlock.theCodeResources[i].theCodeThing.theShutdownTask.theFlags);
  364.     gTheParamBlock.theCodeResources[i].theAddress = theCode;
  365.  
  366.  
  367.     // Return any errors
  368.     return(noErr);
  369. }
  370.  
  371.  
  372.  
  373.  
  374.  
  375.  
  376.  
  377.  
  378.  
  379.  
  380.  
  381.  
  382.  
  383.  
  384.  
  385. //=============================================================================
  386. //        InstallVBLTask : Install a VBL task.                                                         
  387. //-----------------------------------------------------------------------------
  388. OSErr InstallVBLTask(short i, Ptr theCode)
  389. {    VBLTask         *theVblPtr;
  390.     OSErr            theErr;
  391.     
  392.     
  393.     
  394.     
  395.     // Allocate a little block of memory in the System Heap for the task information
  396.     theVblPtr = (VBLTask*) NewPtrSys(sizeof(VBLTask));
  397.     
  398.     
  399.     
  400.     // Fill in the fields, and install it as a VBL task
  401.     theVblPtr->qType    = vType;
  402.     theVblPtr->vblAddr  = NewVBLProc(theCode);
  403.     theVblPtr->vblCount = gTheParamBlock.theCodeResources[i].theCodeThing.theVBLTask.vblCount;
  404.     theVblPtr->vblPhase = gTheParamBlock.theCodeResources[i].theCodeThing.theVBLTask.vblPhase;
  405.     theErr = VInstall((QElemPtr) theVblPtr);
  406.     
  407.     
  408.     
  409.     // Save the address of the VBLTask structure in the address table and the param block
  410.     if (theErr == noErr)
  411.         {
  412.         gTheESAddressTable->theTable[i]                    = (ProcPtr) theVblPtr;
  413.         gTheParamBlock.theCodeResources[i].theAddress    = (Ptr) theVblPtr;
  414.         }
  415.     
  416.     
  417.     // Return any errors
  418.     return(theErr);
  419. }
  420.  
  421.  
  422.  
  423.  
  424.  
  425.  
  426.  
  427.  
  428.  
  429.  
  430.  
  431.  
  432.  
  433.  
  434.  
  435. //=============================================================================
  436. //        InstallLowMemFilter : Install a low-memory filter.                                                         
  437. //-----------------------------------------------------------------------------
  438. OSErr InstallLowMemFilter(short i, Ptr theCode)
  439. {    ProcPtr        theEntryPoint;
  440.     
  441.  
  442.  
  443.     
  444.     // Get the address of the filter chain.
  445.     theEntryPoint = (ProcPtr) gTheParamBlock.theCodeResources[i].theCodeThing.theLowMemFilter.theEntryPoint;
  446.     
  447.     
  448.     
  449.     // Save the address currently at the front of the chain in the address table
  450.     // and save ourselves in the param block.
  451.     gTheESAddressTable->theTable[i]                    = (ProcPtr) *((void **) theEntryPoint);
  452.     gTheParamBlock.theCodeResources[i].theAddress    = theCode;
  453.     
  454.     
  455.     // Insert ourselves into the front of the chain
  456.     *((long *) theEntryPoint) = (long) theCode;
  457.  
  458.  
  459.     // Return any errors
  460.     return(noErr);
  461. }
  462.  
  463.  
  464.  
  465.  
  466.  
  467.  
  468.  
  469.  
  470.  
  471.  
  472.  
  473.  
  474.  
  475.  
  476.  
  477. //=============================================================================
  478. //        InstallCodeBlock : Install a block of code.                                                         
  479. //-----------------------------------------------------------------------------
  480. OSErr InstallCodeBlock(short i, Ptr theCode)
  481. {    
  482.     
  483.     // Set the reserved field to some value
  484.     gTheParamBlock.theCodeResources[i].theCodeThing.theCodeBlock.refCon = 0xDEADBEEF;
  485.     
  486.     
  487.     
  488.     // Save the address of the code block in the address table and the param block
  489.     gTheESAddressTable->theTable[i]                    = (ProcPtr) theCode;
  490.     gTheParamBlock.theCodeResources[i].theAddress    = theCode;
  491.  
  492.  
  493.     // Return any errors
  494.     return(noErr);
  495. }
  496.  
  497.  
  498.  
  499.  
  500.  
  501.  
  502.  
  503.  
  504.  
  505.  
  506.  
  507.  
  508.  
  509.  
  510.  
  511. //=============================================================================
  512. //        InstallTimeManagerTask : Install a Time Manager task.                                                         
  513. //-----------------------------------------------------------------------------
  514. OSErr InstallTimeManagerTask(short i, Ptr theCode)
  515. {    TMTask             *theTaskPtr;
  516.  
  517.  
  518.  
  519.  
  520.     // Allocate a little block of memory in the System Heap for the task information
  521.     theTaskPtr = (TMTask*) NewPtrSys(sizeof(TMTask));
  522.     
  523.     
  524.     
  525.     // Fill in the fields, and install it as an Time Manager task. We don't install
  526.     // it as with InsXTime because we probably won't need that accurate timing.
  527.     theTaskPtr->tmAddr    = (TimerUPP) theCode;
  528.     theTaskPtr->tmCount    = 0;
  529.     InsTime((QElemPtr) theTaskPtr);
  530.     PrimeTime((QElemPtr) theTaskPtr,
  531.                 gTheParamBlock.theCodeResources[i].theCodeThing.theTimeManagerTask.theDelay);
  532.     
  533.     
  534.     
  535.     // Save the address of the TMTask structure in the address table and the param block
  536.     gTheESAddressTable->theTable[i]                    = (ProcPtr) theTaskPtr;
  537.     gTheParamBlock.theCodeResources[i].theAddress    = (Ptr) theTaskPtr;
  538.     
  539.     
  540.     
  541.     // Return any errors
  542.     return(noErr);
  543. }
  544.